package com.cby.android.olive.encrypt

import com.cby.android.olive.encrypt.Base64Utils.decodeToByte
import com.cby.android.olive.encrypt.Base64Utils.encode
import java.security.KeyFactory
import java.security.KeyPairGenerator
import java.security.spec.PKCS8EncodedKeySpec
import java.security.spec.X509EncodedKeySpec
import javax.crypto.Cipher

/**
 * Description:RSA加密解密工具类----RSA非对称加密，公钥加密-私钥解密，私钥加密-公钥解密
 *
 * @author 陈宝阳
 * @create 2019/5/23 09: 40
 */
object RSAEncryptUtil {

    /** 非对称加密密钥算法*/
    private const val RSA = "RSA";

    /** 加密填充方式*/
    private const val ECB_PKCS1_PADDING = "RSA/ECB/PKCS1Padding"

    /** 秘钥默认长度*/
    private const val DEFAULT_KEY_SIZE = 2048

    /** 当要加密的内容超过bufferSize，则采用partSplit进行分块加密*/
    private val DEFAULT_SPLIT = "#PART#".toByteArray()

    /** 当前秘钥支持加密的最大字节数*/
    private const val DEFAULT_BUFFER_SIZE = (DEFAULT_KEY_SIZE / 8) - 11

    /**
     * 随机生成RSA密钥对
     *
     * @param keyLength 密钥长度，范围：512～2048  一般1024
     * @return
     */
    fun generateRSAKeyPair(keyLength: Int): HashMap<Int, String?> {
        val map = HashMap<Int, String?>();

        val kpg = KeyPairGenerator.getInstance(RSA)
        kpg.initialize(keyLength)
        val keyPair = kpg.genKeyPair()
        val privateKey =  keyPair.private   // 得到私钥
        val publicKey = keyPair.public  // 得到公钥

        val publicKeyString = encode(publicKey.encoded)
        // 得到私钥字符串
        val privateKeyString = encode(privateKey.encoded)
        // 将公钥和私钥保存到Map
        map[0] = publicKeyString;  //0表示公钥
        map[1] = privateKeyString;  //1表示私钥
        return map
    }

    /**
     * RSA公钥加密(先数据RSA加密，再Base64加密)
     *
     * @param str 加密字符串
     * @param publicKey 公钥 （有经过base64加密过）
     * @return 密文
     */
    @Throws(Exception::class)
    fun encryptByPublicKey(str: String, publicKey: String): String? {
        //base64编码的公钥
        val decoded = decodeToByte(publicKey)

        val keySpec = X509EncodedKeySpec(decoded)
        val kf = KeyFactory.getInstance(RSA)
        val pubKey = kf.generatePublic(keySpec)

        //RSA加密
        val cipher = Cipher.getInstance(ECB_PKCS1_PADDING)
        cipher.init(Cipher.ENCRYPT_MODE, pubKey)
        return encode(cipher.doFinal(str.toByteArray(charset("UTF-8"))))
    }

    /**
     * RSA公钥解密(先数据Base64解密，在RSA解密)
     *
     * @param str 待解密数据
     * @param publicKey 密钥 （有经过base64加密过）
     * @return byte[] 解密后的明文数据
     */
    @Throws(Exception::class)
    fun decryptByPublicKey(str: String?, publicKey: String): String {

        //64位解码加密后的字符串
        val inputByte = decodeToByte(str)
        //base64编码的公钥
        val decoded = decodeToByte(publicKey)
        val keySpec = X509EncodedKeySpec(decoded)
        val kf = KeyFactory.getInstance(RSA)
        val keyPublic = kf.generatePublic(keySpec)

        // RSA数据解密
        val cipher = Cipher.getInstance(ECB_PKCS1_PADDING)
        cipher.init(Cipher.DECRYPT_MODE, keyPublic)
        return String(cipher.doFinal(inputByte))
    }

    /**
     * RSA私钥加密
     *
     * @param str       待加密数据
     * @param privateKey 密钥  （有经过base64加密过）
     * @return byte[] 加密数据
     */
    @Throws(Exception::class)
    fun encryptByPrivateKey(str: String, privateKey: String): String? {

        //base64编码的私钥
        val decoded = decodeToByte(privateKey)
        // 得到私钥
        val keySpec = PKCS8EncodedKeySpec(decoded)
        val kf = KeyFactory.getInstance(RSA)
        val keyPrivate = kf.generatePrivate(keySpec)
        // 数据加密
        val cipher = Cipher.getInstance(ECB_PKCS1_PADDING)
        cipher.init(Cipher.ENCRYPT_MODE, keyPrivate)
        return encode(cipher.doFinal(str.toByteArray(charset("UTF-8"))))
    }

    /**
     * RSA私钥解密
     *
     * @param str      待解密数据
     * @param privateKey 密钥
     * @return byte[] 解密数据
     */
    @Throws(java.lang.Exception::class)
    fun decryptByPrivateKey(str: String?, privateKey: String?): String? {

        //64位解码加密后的字符串
        val inputByte = decodeToByte(str)
        //base64编码的公钥
        val decoded = decodeToByte(privateKey)

        // 得到私钥
        val keySpec = PKCS8EncodedKeySpec(decoded)
        val kf = KeyFactory.getInstance(RSA)
        val keyPrivate = kf.generatePrivate(keySpec)

        // 解密数据
        val cp = Cipher.getInstance(ECB_PKCS1_PADDING)
        cp.init(Cipher.DECRYPT_MODE, keyPrivate)
        return String(cp.doFinal(inputByte))
    }
}